package ms.utils;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import ms.jasim.framework.IMessageConsole;
import ms.jasim.framework.JasimFramework;

public class PerformanceTimer {
	
	public static class PerformanceEntry {
		private String name, text;
		private long start, end;
		private List<PerformanceEntry> nestedEntry;
		private PerformanceEntry parent;
		
		public PerformanceEntry(String name, String text) {
			this.name = name;
			this.text = text;
			this.start = System.nanoTime();
		}
		
		public void complete() {
			end = System.nanoTime();
		}
		
		public String getName() {
			return name;
		}
		
		public String getText() {
			return text;
		}
		
		public long getStart() {
			return start;
		}
		
		public long getEnd() {
			return end;
		}
	
		public PerformanceEntry addNestedEntry(PerformanceEntry entry) {
			if (nestedEntry == null)
				nestedEntry = new ArrayList<PerformanceEntry>();
			nestedEntry.add(entry);
			entry.parent = this;
			return entry;
		}

		PerformanceEntry getParent() {
			return parent;
		}
	}

	private static PerformanceEntry currentEntry;
	
	public static PerformanceEntry createEntry(String name, String text) {
		PerformanceEntry entry = new PerformanceEntry(name, text);
		if (currentEntry != null)
			currentEntry.addNestedEntry(entry);
		currentEntry = entry;
		return entry;
	}
	
	public static PerformanceEntry closeEntry() {
		PerformanceEntry result = currentEntry;
		if (result != null) {
			result.complete();
			if (result.getParent() != null) currentEntry = result.getParent();
		}
		return result;
		
	}

	public static void dumpEntries(IMessageConsole console) {
		if (currentEntry != null) {
			String tab = "";
			StringBuilder builder = new StringBuilder();
			PerformanceEntry entry = currentEntry;
			
			Stack<PerformanceEntry> stack = new Stack<PerformanceEntry>();
			Stack<Integer> levelStack = new Stack<Integer>();
			
			stack.add(entry);
			levelStack.add(0);
			
			while (!stack.isEmpty()) {
				
				entry = stack.pop();
				int level = levelStack.pop();
				for (int i = 0; i < level; i++)
					builder.append('\t');
				
				float res = (entry.getEnd() - entry.getStart());
				builder.append(String.format("%s: %f", entry.getText(), res/10e6 ));
				builder.append("\r\n");
				if (entry.nestedEntry != null) {
					for (int i = entry.nestedEntry.size() - 1; i >= 0; i--) {
						stack.add(entry.nestedEntry.get(i));
						levelStack.add(level + 1);
					}
				}
			}
			if (console != null)
				console.write("Performance", builder.toString());
			else
				System.out.println(builder.toString());
			
			currentEntry = currentEntry.getParent();
		}
	}
	
	public static void dumpEntries() {
		IMessageConsole console = JasimFramework.getService(null, IMessageConsole.class);
		dumpEntries(console);
	}
}
